﻿// Bing Maps ASP.NEt Control is a community project available under the Microsoft Public License (Ms-PL)
// Code is provided as is and with no warrenty – Use at your own risk
// View the project and the latest code at http://BingMapsASP.codeplex.com

/// <reference name="MicrosoftAjax.js" />
Type.registerNamespace("Microsoft.Live.ClientControls.VE") ; 

Microsoft.Live.ClientControls.VE.EventArgs = function(_mapEvent) 
{
    this._mapEvent = _mapEvent;
    this._cancelEventArgs = new Sys.CancelEventArgs();
}

Microsoft.Live.ClientControls.VE.EventArgs.prototype = 
{
    get_MapEvent : function()      
    {   
        return this._mapEvent;     
    },
    set_cancel : function (value)
    {
        this._cancelEventArgs.set_cancel(value);
    },
    get_cancel : function()
    {
        return this._cancelEventArgs.get_cancel();
    }
}

Microsoft.Live.ClientControls.VE.EventArgs.registerClass('Microsoft.Live.ClientControls.VE.EventArgs', null, Sys.IDisposable);

Microsoft.Live.ClientControls.VE.Map = function(element) {
    /// <summary>
    ///   The Microsoft Live Server Controls VE Map client side code.
    /// </summary>
    /// <param name="element">The div element to be made into the VE map.</param>
    Microsoft.Live.ClientControls.VE.Map.initializeBase(this, [element]) ;
    
    //The VEMap object
    this._map = null;
    
    //private VE properties
    this._vEAPINotFound;
    this._browsersNotSupported;
    this._height;
    this._width;
    this._center;
    this._mapMode;
    this._mapStyle;
    this._navigationControl3D;
    this._dashboard;
    this._dashboardSize;
    this._miniMap;
    this._miniMapXoffset;
    this._miniMapYoffset;
    this._miniMapSize;
    this._trafficLegend;
    this._trafficLegendX;
    this._trafficLegendY;
    this._traffic;
    this._enableShapeDisplayThreshold;
    this._mouseWheelZoomToCenter;
    this._scaleBarDistanceUnit;
    this._shapesAccuracy;
    this._shapesAccuracyRequestLimit;
    this._tileBuffer;
    this._trafficLegendText;
    this._zoomLevel;
    this._disambiguationDialog;
    this._clearInfoBoxStyles;
    this._fixedMap;
    this._showMapModeSwitch;
    this._showFindControl;
    this._altitude;
    this._heading;
    this._pitch;
    this._failedShapeRequest;    
    this._clientToken;    
    this._SendLayersToServer;
    
    //server side event enabled
    this._onServerLoadMap = false;
    this._onServerChangeMapStyle = false;
    this._onServerChangeView = false;
    this._onServerEndPan = false;
    this._onServerEndZoom = false;
    this._onServerError = false;
    // Issue:27368 - Removed since this event is to be disabled/removed from the api
    //this._onServerInitMode = false;
    this._onServerModeNotAvailable = false;
    this._onServerObliqueChange = false;
    this._onServerObliqueEnter = false;
    this._onServerObliqueLeave = false;
    this._onServerResize = false;
    this._onServerClick = false;
    this._onServerDoubleClick = false; 
    this._onServerFind = false;    
    this._onServerGetDirections = false;    
    this._onServerTokenError = false;    
    this._onServerTokenExpire = false;    
    
    //private panels/controls for communication with server
    this._mapContainerID;
    this._asyncTriggerID;
    this._mapDataID;
    this._mapChangesID;
    this._commandsID;
    this._commsFlagID;
    this._inprogress = true;
    this._messages = new Array();  
    
    //events handler delgates for postback event
    this._onFormSubmitDelegate;
    this.__doPostBackDelegate;
    this._original__doPostBack;
    
    //storage for property changes
    this._propertyChanges = new Array();
    
} 

Microsoft.Live.ClientControls.VE.Map.prototype = {

    //initialize / setup
    initialize : function() {
        /// <summary>
        ///   Initialises the Map.
        /// </summary>       
        Microsoft.Live.ClientControls.VE.Map.callBaseMethod(this, 'initialize') ;
        
        //Bind to all form submits
        this._onFormSubmitDelegate = Function.createDelegate(this, this._onPagePostBack);
        var forms = document.getElementsByTagName("form");
        for (var x=0;x<forms.length;x++) {
            $addHandler(forms[x],"submit",this._onFormSubmitDelegate);
        }
        this._original__doPostBack = __doPostBack;
        this.__doPostBackDelegate = Function.createDelegate(this, this.__doPostBack);
        __doPostBack = this.__doPostBackDelegate;
        
        //verify VEAPI has loaded
        if (typeof(VEMap) != "undefined") {
            //verify Browser is supported
            if (
                //IE6 or above
                (Sys.Browser.agent == Sys.Browser.InternetExplorer && Sys.Browser.version >= 6) || 
                //FF2 or above
                (Sys.Browser.agent == Sys.Browser.Firefox && Sys.Browser.version >= 2) || 
                //Safari 2 or above
                (Sys.Browser.agent == Sys.Browser.Safari && Sys.Browser.version >= 2)
                ) {
                this._createVEMap();
            }else {
                $get(this._mapContainerID).innerHTML = this._browsersNotSupported;
            }
        }else {
            $get(this._mapContainerID).innerHTML = this._vEAPINotFound;
        } 
    },
     
    _createVEMap: function() {
        this._disposeVEMap();
        this._map = new VEMap(this._mapContainerID);
        //Client token support
        if (this._clientToken.length > 0) this._map.SetClientToken(this._clientToken);
        //Dashboard selections
        if (this._dashboard) this._map.SetDashboardSize(this._dashboardSize);
        //Listen for when map is loaded to perform operations
        this._map.onLoadMap = Function.createDelegate(this, this._onLoadVEMap);        
        this._map.LoadMap(this._parseVELatLong(this._center), this._zoomLevel, this._mapStyle, this._fixedMap, this._mapMode, this._showMapModeSwitch, this._tileBuffer);
    
    },
    
    _parseVELatLong: function (_loc) {
        if(_loc.Altitude)
        {
            return new VELatLong(_loc.Latitude, _loc.Longitude, _loc.Altitude, _loc.AltitudeMode);
            }
        else{    
            return new VELatLong(_loc.Latitude, _loc.Longitude);
        }
    },
    
//    _intToAltitudeMode: function (alt)
//    {
//        switch(alt)
//        {
//            case 0:
//                return VEAltitudeMode.Default;
//            case 1:
//                return VEAltitudeMode.Absolute;
//            case 2:
//                return VEAltitudeMode.RelativeToGround;               
//        }
//        return VEAltitudeMode.Default;
//    },
//    
    _parseVELatLongArray: function (_array) {
        var _vearray = new Array();
        for (var orect in _array) {
            _vearray.push(this._parseVELatLong(_array[orect]));
        }
        return _vearray;
    },    
    
    _parseVEPixel: function (_pixel) {
        return new VEPixel(_pixel.x, _pixel.y);
    },    
    
    _parseVELatLongRectangleArray : function (_array) {
        var _vearray = new Array();
        for (var orect in _array) {
            _vearray.push(this._parseVELatLongRectangle(_array[orect]));
        }
        return _vearray;
    },  
    
    _parseVELatLongRectangle : function (_rect) {
        return new VELatLongRectangle(this._parseVELatLong(_rect.TopLeftLatLong), this._parseVELatLong(_rect.BottomRightLatLong));
    },     
    
    _parseVEColor: function (_color) {
        return new VEColor(_color.R, _color.G, _color.B, _color.A);
    },
    
    _convertColor: function (_vecolor) {
        return {"A":_vecolor.A,"R":_vecolor.R,"G":_vecolor.G,"B":_vecolor.B};
    },
    
    _parseVEShapeLayer: function (_l) {
        var layer = new VEShapeLayer();
        layer.SetDescription(_l.Description);
        layer.SetTitle(_l.Title);      
        return layer;
    },
    
    _parseVECustomIconSpecification: function (_spec) {
        var vespec = new VECustomIconSpecification();
        vespec.BackColor = this._parseVEColor(_spec.BackColor);
        vespec.CustomHTML = _spec.CustomHTML;   
        vespec.ForeColor = this._parseVEColor(_spec.ForeColor);   
        vespec.Image = _spec.Image;   
        vespec.ImageOffset = this._parseVEPixel(_spec.ImageOffset);   
        vespec.TextBold = _spec.TextBold;   
        vespec.TextContent = _spec.TextContent;   
        vespec.TextFont = _spec.TextFont;   
        vespec.TextItalics = _spec.TextItalics;   
        vespec.TextOffset = this._parseVEPixel(_spec.TextOffset);   
        vespec.TextSize = _spec.TextSize;   
        vespec.TextUnderline = _spec.TextUnderline;   
        return vespec;
    },
    
    _disposeVEMap: function() {
       if (this._map) {
            this._map.Dispose();
            this._map = null;
        }    
    },    
    
    _onLoadVEMap: function() {
        /// <summary>
        ///   Executes on map load, sets the basic map properties, binds event handlers.
        /// </summary>  
        
        //set properties  
        this._map.SetScaleBarDistanceUnit(this._scaleBarDistanceUnit);
        this._map.EnableShapeDisplayThreshold(this._enableShapeDisplayThreshold);
        this._map.SetMouseWheelZoomToCenter(this._mouseWheelZoomToCenter);
        this._map.SetFailedShapeRequest(this._failedShapeRequest);
        this._map.SetShapesAccuracy(this._shapesAccuracy);
        this._map.SetShapesAccuracyRequestLimit(this._shapesAccuracyRequestLimit);
        this._map.ShowDisambiguationDialog(this._disambiguationDialog);  
                
        if (!this._dashboard) {
            this._map.HideDashboard();
        }
        
        if (this._miniMap){
            this._map.ShowMiniMap(this._miniMapXoffset, this._miniMapYoffset, this._miniMapSize);
        }
        
        if (this._clearInfoBoxStyles) {
            this._map.ClearInfoBoxStyles();
        }
        
        if (!this._navigationControl3D) {
            this._map.Hide3DNavigationControl();
        }
        
        if (this._showFindControl) {
            this._map.ShowFindControl();
        }        
        
        if (this._traffic && this._clientToken) {
            this._map.LoadTraffic(this._traffic);
            if (this._trafficLegend) {
                if (this._trafficLegendX > -1 && this._trafficLegendY > -1) {
                    this._map.ShowTrafficLegend(this._trafficLegendX, this._trafficLegendY)
                }else {
                    this._map.ShowTrafficLegend()
                }
                if (this._trafficLegendText) {
                    this._map.SetTrafficLegendText(this._trafficLegendText);
                }
            }
        }
        
        if (this._map.GetMapMode() == VEMapMode.Mode3D) {
            //Ignore default value 0m, use Zoomlevel instead.
            if (this._altitude > 0) {
                this._map.SetAltitude(this._altitude);
            }
            this._map.SetHeading(this._heading);
            this._map.SetPitch(this._pitch);
        }  
        
        //Listen for Async Postback Communications
        Sys.Application.add_load(Function.createDelegate(this, this._onPostback));
        
        //Start processing
        this._inprogress = false;
        
        //set events
        this._map.AttachEvent("onchangemapstyle", Function.createDelegate(this,this._raiseOnClientChangeMapStyle));
        this._map.AttachEvent("onchangeview", Function.createDelegate(this,this._raiseOnClientChangeView));
        this._map.AttachEvent("onendpan", Function.createDelegate(this,this._raiseOnClientEndPan));
        this._map.AttachEvent("onendzoom", Function.createDelegate(this,this._raiseOnClientEndZoom));
        this._map.AttachEvent("onerror", Function.createDelegate(this,this._raiseOnClientError));
        // Issue:27368 - Removed since this event is to be disabled/removed from the api
        // this._map.AttachEvent("oninitmode", Function.createDelegate(this,this._raiseOnClientInitMode));
        this._map.AttachEvent("onmodenotavailable", Function.createDelegate(this,this._raiseOnClientModeNotAvailable));
        this._map.AttachEvent("onobliquechange", Function.createDelegate(this,this._raiseOnClientObliqueChange));
        this._map.AttachEvent("onobliqueenter", Function.createDelegate(this,this._raiseOnClientObliqueEnter));
        this._map.AttachEvent("onobliqueleave", Function.createDelegate(this,this._raiseOnClientObliqueLeave));
        this._map.AttachEvent("onresize", Function.createDelegate(this,this._raiseOnClientResize));
        this._map.AttachEvent("onstartpan", Function.createDelegate(this,this._raiseOnClientStartPan));
        this._map.AttachEvent("onstartzoom", Function.createDelegate(this,this._raiseOnClientStartZoom));
        this._map.AttachEvent("onkeypress", Function.createDelegate(this,this._raiseOnClientKeyPress));
        this._map.AttachEvent("onkeydown", Function.createDelegate(this,this._raiseOnClientKeyDown));
        this._map.AttachEvent("onkeyup", Function.createDelegate(this,this._raiseOnClientKeyUp));
        this._map.AttachEvent("onclick", Function.createDelegate(this,this._raiseOnClientClick));
        this._map.AttachEvent("ondoubleclick", Function.createDelegate(this,this._raiseOnClientDoubleClick));
        this._map.AttachEvent("onmousedown", Function.createDelegate(this,this._raiseOnClientMouseDown));
        this._map.AttachEvent("onmousemove", Function.createDelegate(this,this._raiseOnClientMouseMove));
        this._map.AttachEvent("onmouseout", Function.createDelegate(this,this._raiseOnClientMouseOut));
        this._map.AttachEvent("onmouseover", Function.createDelegate(this,this._raiseOnClientMouseOver));
        this._map.AttachEvent("onmouseup", Function.createDelegate(this,this._raiseOnClientMouseUp));
        this._map.AttachEvent("onmousewheel", Function.createDelegate(this,this._raiseOnClientMouseWheel));
        if (this._clientToken.length > 0) { 
            this._map.AttachEvent('ontokenexpire', Function.createDelegate(this,this._raiseOnClientTokenExpire));
            this._map.AttachEvent('ontokenerror', Function.createDelegate(this,this._raiseOnClientTokenError));
        }
                
        //Raise loaded event
        this._raiseOnClientLoadMap();    
    },
    
    //events for communication with server
    
    _onPostback : function(e, a) {
        //Validate Server -> client data
        var commsflag = $get(this._commsFlagID).value;
        if (commsflag == "1") {
            // set properties that have changed
            var propertiesString = $get(this._mapChangesID).value;
            if (propertiesString.length > 0) {
                var propertyobj = Sys.Serialization.JavaScriptSerializer.deserialize(propertiesString);
                Sys$Component$_setProperties(this, propertyobj);
            } 
                   
           //load map data
            var dataString = $get(this._mapDataID).value;
            if (dataString.length > 0) {
                var dataobj = Sys.Serialization.JavaScriptSerializer.deserialize(dataString);
                this._executeData(dataobj);
            }
           
            //look for commands after data loads, don't want to clear routes, messages etc.
            var commandString = $get(this._commandsID).value;
            if (commandString.length > 0) {
                var commandobj = Sys.Serialization.JavaScriptSerializer.deserialize(commandString);
                this._executeMethods(commandobj);
            }

            
        }
        
        //Set processing flag
        this._inprogress = false;
        if (this._messages.length > 0) {
            this._sendAsyncMessages();
        }                  
    },
    
    _executeMethods: function(methods) {
        for (var name in methods) {
            var val = methods[name];
            var method = this[val.MethodName];
            if (val.Params) {
                method.apply(this, val.Params);
            } else {
                method.call(this);
            }
            
        }
    },
    
    _executeData: function(data) {
        
        //Look for clear command
        if (data.Clear) {
            this._map.Clear();
            //reset Traffic if true. Bug in VE API that disables traffic on Clear().
            if (this.get_Traffic() == true) {
                this.set_Traffic(false);
                this.set_Traffic(true);
            }
        }
        
        //Delete shape layers
        if (data.DeletedShapeLayers) {
            for (var obinding in data.DeletedShapeLayers) {
                var _velayer = this._GetShapeLayerByID(data.DeletedShapeLayers[obinding]);
                if (_velayer) {
                    this._map.DeleteShapeLayer(_velayer);
                }
            }  
        }
        
        //Delete shapes
        if (data.DeletedShapes) {
            for (var obinding in data.DeletedShapes) {
                var _veshape = this._map.GetShapeByID(data.DeletedShapes[obinding]);
                if (_veshape) {
                    this._map.DeleteShape(_veshape);
                }
            }                  
        }
        
        //Delete tile layers
        if (data.DeletedTileLayers) {
            for (var obinding in data.DeletedTileLayers) {
                var _velayer = this._map.GetTileLayerByID(data.DeletedTileLayers[obinding]);
                if (_velayer) {
                    this._map.DeleteTileLayer(_velayer.ID);
                }
            }   
        }         
        
        //Add shapes layers with shapes
        if (data.ShapeLayers) {
            for (var olayer in data.ShapeLayers) {
                var l = data.ShapeLayers[olayer];
                if (l.BaseLayer) {
                    //base shapes directly to map
                    this._addShapesToLayer(l.Shapes, this._map);
                }else {
                    var layer = this._parseVEShapeLayer(l);
                    this._map.AddShapeLayer(layer);
                    this._addShapesToLayer(l.Shapes, layer);
                    if (!l.Visible) {
                        layer.Hide();
                    }
                }
            }
        } 
               
        //Add tile layers
        if (data.TileLayers) {
            for (var olayer in data.TileLayers) {
                var l = data.TileLayers[olayer];
                
                // Issue: 16707 - Virtual Earth: SendLayersToServer="false" throws error when set from server side.
                // Don't add the tile unless it has State = Added(=2)
                if (l.State==2)
                {
                    var GetTilePathFunction;
                    if (l.GetTilePath) {
                        GetTilePathFunction = eval(l.GetTilePath);
                    }
                    var layer = new VETileSourceSpecification(l.ID, l.TileSource, l.NumServers, this._parseVELatLongRectangleArray(l.Bounds), l.MinZoom, l.MaxZoom, GetTilePathFunction, l.Opacity, l.ZIndex);
                    this._map.AddTileLayer(layer, l.Visible);            
                }
            }
        }
        
        //Modified Shape Layers
        if (data.ModifiedShapeLayers) {
            for (var olayer in data.ModifiedShapeLayers) {
                var l = data.ModifiedShapeLayers[olayer];
                var layer = this._GetShapeLayerByID(l.ID);
                if (layer) {
                    if (l.Description) {
                        layer.SetDescription(l.Description);
                    }                    
                    if (l.Title) {
                        layer.SetTitle(l.Title);
                    }  
                    if (l.Visible) {
                        layer.Show();
                    }
                    if (l.Visible == false) {
                        layer.Hide();
                    }                                        
                    if (l.ModifiedShapes) {
                        for (var oshapes in l.ModifiedShapes) {
                            var s = l.ModifiedShapes[oshapes];
                            var shape = this._map.GetShapeByID(s.ID);
                            if (s.Points) {
                                var points = new Array();
                                for (opoint in s.Points) {
                                    points.push(this._parseVELatLong(s.Points[opoint]));
                                }
                                shape.SetPoints(points);
                            }
                            if (s.Altitude) {
                                shape.SetAltitude(s.Altitude);
                            }
                            if (s.AltitudeMode) {
                                shape.SetAltitudeMode(this._validateAltitudeMode(s.AltitudeMode));
                            }
                            if (s.CustomIconSpec) {
                                shape.SetCustomIcon(this._parseVECustomIconSpecification(s.CustomIconSpec));
                            }
                            if (s.CustomIcon) {
                                shape.SetCustomIcon(s.CustomIcon);
                            }
                            if (s.Description) {
                                shape.SetDescription(s.Description);
                            }
                            if (s.IconAnchor) {
                                shape.SetIconAnchor(this._parseVELatLong(s.IconAnchor));
                            }
                            if (s.LineToGround) {
                                shape.SetLineToGround(s.LineToGround);
                            }
                            if (s.MaxZoomLevel) {
                                shape.SetMaxZoomLevel(s.MaxZoomLevel);
                            }
                            if (s.MinZoomLevel) {
                                shape.SetMinZoomLevel(s.MinZoomLevel);
                            }
                            if (s.MoreInfoURL) {
                                shape.SetMoreInfoURL(s.MoreInfoURL);
                            }
                            if (s.PhotoURL) {
                                shape.SetPhotoURL(s.PhotoURL);
                            }
                            if (s.Title) {
                                shape.SetTitle(s.Title);
                            }
                            if (s.ZIndex) {
                                shape.SetZIndex(s.ZIndex);
                            }
                            if (s.Visible) {
                                shape.Show();
                            }
                            if (s.Visible == false) {
                                shape.Hide();
                            }
                            if (s.IconVisible) {
                                shape.ShowIcon();
                            }
                            if (s.IconVisible == false) {
                                shape.HideIcon();
                            }            

                            if (s.LineWidth) {
                                shape.SetLineWidth(s.LineWidth);
                            }
                            if (s.LineColor) {
                                shape.SetLineColor(this._parseVEColor(s.LineColor));
                            }
                            if (s.FillColor) {
                                shape.SetFillColor(this._parseVEColor(s.FillColor));
                            }
                        }
                    }
                    if (l.Shapes) {
                        if (l.BaseLayer) {
                            this._addShapesToLayer
                            (l.Shapes, this._map);
                        } else {
                            this._addShapesToLayer(l.Shapes, layer);
                        }
                    }               
                }
            }
        }
                
        //Modified Tile Layers
        if (data.ModifiedTileLayers) {
            for (var olayer in data.ModifiedTileLayers) {
                var l = data.ModifiedTileLayers[olayer];
                var layer = this._map.GetTileLayerByID(l.ID);
                var refresh = false;
                if (layer) {
                    //change properties
                    if (l.TileSource) {
                        layer.TileSource = l.TileSource;
                        refresh = true;
                    }
                    if (l.NumServers ) {
                        layer.NumServers = l.NumServers;
                        refresh = true;
                    }
                    if (l.Bounds) {
                        layer.Bounds = this._parseVELatLongRectangleArray(l.Bounds);
                        refresh = true;
                    }
                    if (l.MinZoom) {
                        layer.MinZoomLevel = l.MinZoom;
                        refresh = true;
                    }
                    if (l.MaxZoom) {
                        layer.MaxZoomLevel = l.MaxZoom;
                        refresh = true;
                    }
                    if (l.GetTilePath) {
                        layer.GetTilePath = l.GetTilePath;
                        refresh = true;
                    }
                    if (l.Opacity) {
                        layer.Opacity = l.Opacity;
                        refresh = true;
                    }
                    if (l.ZIndex) {
                        layer.ZIndex = l.ZIndex;
                        refresh = true;
                    }
                    if (l.Visible) {
                        this._map.ShowTileLayer(l.ID);
                    }
                    if (l.Visible == false) {
                        this._map.HideTileLayer(l.ID);
                    }
                }
                if (refresh) {
                    this._map.DeleteTileLayer(l.ID);
                    var newlayer = new VETileSourceSpecification(layer.ID, layer.TileSource, layer.NumServers, layer.Bounds, layer.MinZoomLevel, layer.MaxZoomLevel, layer.GetTilePath, layer.Opacity, layer.ZIndex);
                    this._map.AddTileLayer(newlayer, l.Visible);
                }    
            }
        }               
    },
    
    _GetShapeLayerByID: function(_iD) {
        var _totalLayers = this._map.GetShapeLayerCount();
        for (var _x=0;_x<_totalLayers;_x++) {
            var _layer = this._map.GetShapeLayerByIndex(_x);
            if (_layer.GetId() == _iD) {
                return _layer;
            }
        }
        return null;
    },
    
    _validateAltitudeMode: function(mode)
    {
        if(mode!="Default")
            return mode;
        else 
            return VEAltitudeMode.Default;
    },
    
    _addShapesToLayer: function(shapes, layer) {
        //keep an array of pins to add in bulk, add polygons and polylines instantly
        var _pins = new Array();
        for (var oshape in shapes) {
            var s = shapes[oshape];
            var points = new Array();
            for (opoint in s.Points) {
                points.push(this._parseVELatLong(s.Points[opoint]));
            }
            var shape = new VEShape(s.Type,points);
            shape.SetAltitude(s.Altitude, this._validateAltitudeMode(s.AltitudeMode));
            if (s.CustomIconSpec) {
                shape.SetCustomIcon(this._parseVECustomIconSpecification(s.CustomIconSpec));
            }else {
                shape.SetCustomIcon(s.CustomIcon);
            }
            shape.SetDescription(s.Description);
            if (s.IconAnchor) {
                shape.SetIconAnchor(this._parseVELatLong(s.IconAnchor));
            }
            shape.SetLineToGround(s.LineToGround);
            shape.SetMaxZoomLevel(s.MaxZoomLevel);
            shape.SetMinZoomLevel(s.MinZoomLevel);
            shape.SetMoreInfoURL(s.MoreInfoURL);
            shape.SetPhotoURL(s.PhotoURL);
            shape.SetTitle(s.Title);
            shape.SetZIndex(s.ZIndex);
            if (!s.Visible) {
                shape.Hide();
            }
            if (!s.IconVisible) {
                shape.HideIcon();
            }            
            if (s.Type == VEShapeType.Pushpin) {
                _pins.push(shape);
            }else {
                shape.SetLineWidth(s.LineWidth);
                shape.SetLineColor(this._parseVEColor(s.LineColor));
                shape.SetFillColor(this._parseVEColor(s.FillColor));
                layer.AddShape(shape);
            }
        }
        if (_pins.length > 0) {
            layer.AddShape(_pins);
        }        
    },          
      
    _sendAsyncEventMessage : function(message, param) {
        this._addKeyPairUpdate(message, param, this._messages);
        if (this._inprogress == false) {
            this._sendAsyncMessages();
        }
    },
    
    _sendAsyncMessages: function() {
        this._inprogress = true;
        $get(this._asyncTriggerID).value = this._arrayKeyPairToJSON(this._messages);
        this._messages = new Array();
        __doPostBack(this._asyncTriggerID);    
    },
    
    _onPagePostBack : function() {
        //store latest map state for server side code.
        //get the latest map poperties, unfortunalty we cannot rely on our methods changing the map properties so we need to refresh them.

        //Center
        this.set_Center(this._map.GetCenter());
        //Zoomlevel
        this.set_ZoomLevel(this._map.GetZoomLevel());
        //Style
        this.set_MapStyle(this._map.GetMapStyle());
        //Mode
        var _mapmode = this._map.GetMapMode()
        this.set_MapMode(_mapmode);
        if (_mapmode == VEMapMode.Mode3D) {
            this.set_Altitude(this._map.GetAltitude());
            this.set_Heading(this._map.GetHeading());
            this.set_Pitch(this._map.GetPitch());
        }
        //Readonly values
        //MapView
        this._OnPropertyChanged("MapView",this._map.GetMapView());
        //if we are in Birdseye we call birdseyeScene and set IsAvailable to true, else we have to call VE method.
        if((this._mapStyle==VEMapStyle.Birdseye)||(this._mapStyle==VEMapStyle.BirdseyeHybrid)){
            //CurrentBirdseyeScene - custom object with properties rather then methods
            var _veBirdseyeScene = this._map.GetBirdseyeScene();
            if (_veBirdseyeScene) {
                var _currentBirdseyeScene = {
                    "BoundingRectangle": _veBirdseyeScene.GetBoundingRectangle(),
                    "Height": _veBirdseyeScene.GetHeight(),
                    "ID": _veBirdseyeScene.GetID(),
                    "Orientation": _veBirdseyeScene.GetOrientation(),
                    "ThumbnailFilename": _veBirdseyeScene.GetThumbnailFilename(),
                    "Width": _veBirdseyeScene.GetWidth()
                };
                this._OnPropertyChanged("CurrentBirdseyeScene",_currentBirdseyeScene);
            }
            //IsBirdseyeAvailable - obviously yes
            this._OnPropertyChanged("IsBirdseyeAvailable",true);
        }else {
            //IsBirdseyeAvailable
            this._OnPropertyChanged("IsBirdseyeAvailable",this._map.IsBirdseyeAvailable());
        }
        
        //Set data comms flag to client write.
        $get(this._commsFlagID).value = "0";

        //call a method to change array to a json string
        $get(this._mapChangesID).value = this._arrayKeyPairToJSON(this._propertyChanges);
        //clear the changes to date
        this._propertyChanges = new Array();
        
        //save out map data
        if (this._SendLayersToServer) {
            //can't serialize VE object, only the correct fields - parse.
            var _shapeLayers = new Array();
            var _totalShapeLayers = this._map.GetShapeLayerCount(); 
            
            //base layer is index 0
            if (_totalShapeLayers > 0) {            
                for (var _x=0;_x<_totalShapeLayers;_x++) {
                    var _velayer = this._map.GetShapeLayerByIndex(_x);
                    if (_velayer) {
                        _shapeLayers.push({            
                            "ID":_velayer.GetId(),
                            "Title":_velayer.GetTitle(),
                            "Description":_velayer.GetDescription(),
                            "Visible":_velayer.IsVisible(),  
                            "Shapes":this._getShapesFromLayer(_velayer)
                        });   
                    }                           
                }
            }
            
            var _tileLayers = new Array();
            var _totalTileLayers = this._map.GetTileLayerCount(); 
            for (var _x=0;_x<_totalTileLayers;_x++) {
                var _velayer = this._map.GetTileLayerByIndex(_x);
                if (_velayer) {
                    _tileLayers.push({            
                        "Bounds":this._getBoundsFromVEarray(_velayer.Bounds),
                        "GetTilePath":_velayer.GetTilePath,
                        "ID":_velayer.ID,
                        "MaxZoom":_velayer.MaxZoomLevel,
                        "MinZoom":_velayer.MinZoomLevel,
                        "NumServers":_velayer.NumServers,
                        "Opacity":_velayer.Opacity,
                        "TileSource":_velayer.TileSource,
                        "ZIndex":_velayer.ZIndex,
                        "Visible":_velayer.Visible
                    });
                }                        
            }            
                    
            $get(this._mapDataID).value = Sys.Serialization.JavaScriptSerializer.serialize({
                "ShapeLayers":_shapeLayers,
                "TileLayers":_tileLayers
            });            
        }else {
            $get(this._mapDataID).value = "";
        }
    },
    
    _getBoundsFromVEarray: function(boundsArray) {
        var _array = new Array();
        for (var orect in boundsArray) {
            var rect = boundsArray[orect];
            _array.push({"TopLeftLatLong":this._cleanVELatLong(rect.TopLeftLatLong), "BottomRightLatLong":this._cleanVELatLong(rect.BottomRightLatLong)});
        }
        return _array;    
    },

    _escapeHTML: function(str)
    {
        var div = document.createElement('div');
        var text = document.createTextNode(str);
        div.appendChild(text);
        return div.innerHTML;
    },  
    
    _getShapesFromLayer: function(layer) {
        var _shapes = new Array();
        var _totalShapes = layer.GetShapeCount();
        for (var _x=0;_x<_totalShapes;_x++) {
            var _veshape = layer.GetShapeByIndex(_x);
            if (_veshape) {
                //create clean shape object based on valid values.
                var _shape = new Object();
                if (_veshape.GetAltitude()) _shape.Altitude = _veshape.GetAltitude()[0];
                if (_veshape.GetAltitudeMode()) _shape.AltitudeMode = _veshape.GetAltitudeMode();
                //two possible formats, detect
                var _customIcon = _veshape.GetCustomIcon();
                if (_customIcon) {
                    if (_customIcon.BackColor) {
                        _shape.CustomIconSpec = _customIcon;
                    }else {
                        _shape.CustomIcon = _customIcon;
                    }
                }            
                if (_veshape.GetDescription())_shape.Description = this._escapeHTML(_veshape.GetDescription());
                if (_veshape.GetFillColor()) _shape.FillColor = this._convertColor(_veshape.GetFillColor());
                //not a complete latlong object, only need lat long parts.
                var _IconAnchor = _veshape.GetIconAnchor();
                if (_IconAnchor) {
                    _shape.IconAnchor = this._cleanVELatLong(_IconAnchor);
                }
                if (_veshape.GetID()) _shape.ID = _veshape.GetID();
                if (_veshape.GetLineColor()) _shape.LineColor = this._convertColor(_veshape.GetLineColor());
                if (_veshape.GetLineToGround()) _shape.LineToGround = _veshape.GetLineToGround();
                if (_veshape.GetLineWidth()) _shape.LineWidth = _veshape.GetLineWidth();
                if (_veshape.GetMaxZoomLevel()) _shape.MaxZoomLevel = _veshape.GetMaxZoomLevel();
                if (_veshape.GetMinZoomLevel()) _shape.MinZoomLevel = _veshape.GetMinZoomLevel();
                if (_veshape.GetMoreInfoURL()) _shape.MoreInfoURL = _veshape.GetMoreInfoURL();
                if (_veshape.GetPhotoURL()) _shape.PhotoURL = _veshape.GetPhotoURL();
                //no need to check, required field
                var _vepoints = _veshape.GetPoints();
                var _points = new Array();
                for (opnt in _vepoints) {
                    _points.push(this._cleanVELatLong(_vepoints[opnt]));
                }
                _shape.Points = _points;
                if (_veshape.GetTitle()) _shape.Title = this._escapeHTML(_veshape.GetTitle());
                //no need to check, required field
                _shape.Type = _veshape.GetType();
                if (_veshape.GetZIndex()) _shape.ZIndex = _veshape.GetZIndex();
                if (_veshape.GetZIndexPolyShape()) _shape.ZIndexPolyShape = _veshape.GetZIndexPolyShape();
                //Unable to determine visibility so have to assume visible.
                _shape.Visible = true;
                _shape.IconVisible = true;
               if (_veshape.IsModel())  _shape.Model = _veshape.IsModel();
               
               _shapes.push(_shape);
            }
        }
        return _shapes;  
    },
    
    _cleanVELatLong: function(_velatlon) {
        var _latlong = new Object();
        if (_velatlon) {
            if (_velatlon.Latitude) _latlong.Latitude = _velatlon.Latitude;
            if (_velatlon.Longitude) _latlong.Longitude = _velatlon.Longitude;
            if (_velatlon.Altitude) _latlong.Altitude = _velatlon.Altitude;
            if (_velatlon.AltitudeMode) _latlong.AltitudeMode = _velatlon.AltitudeMode;
        }
        return _latlong;
    },

    _OnPropertyChanged: function(name, clientValue) {
        this._addKeyPairUpdate(name, clientValue, this._propertyChanges);
    },
    
    _addKeyPairUpdate: function(_key, _value, _array) {
        var found = false;
        for (oBinding in _array) {
            if (_array[oBinding].Key == _key)
            {
                _array[oBinding].Value = Sys.Serialization.JavaScriptSerializer.serialize(_value);
                found = true;
                break;
            }        
        }
        if (!found)
        {
            _array.push({"Key":_key, "Value":Sys.Serialization.JavaScriptSerializer.serialize(_value)});
        }
    },       
    
    _arrayKeyPairToJSON: function(_array) {
        //loop through array and build JSON string
        if (_array.length > 0)
        {
            var str = new Sys.StringBuilder('{');
            for (oBinding in _array)
            {
                str.append('"');
                str.append(_array[oBinding].Key);
                str.append('":');
                str.append(_array[oBinding].Value);
                str.append(',');
            }
            return str.toString().substr(0,str.toString().length-1) + '}';
        }
        return "";        
    },
    
    __doPostBack : function(eventTarget, eventArgument) {
        this._onPagePostBack();
        this._original__doPostBack(eventTarget, eventArgument);
    },
    
    //Public Methods
    AddControl : function(_element, _zIndex) {
        this._map.AddControl(_element, _zIndex);
    },
    
    AddShape : function(_shape) {
        this._map.AddShape(_shape);
    },
    
    AddShapeLayer : function(_layer) {
        this._map.AddShapeLayer_layer
    },
    
    AddTileLayer : function(_layerSource, _visibleOnLoad) {
        this._map.AddTileLayer(_layerSource, _visibleOnLoad);
    },
    
    Clear : function() {
        this._map.Clear();
    },
    
    DeleteAllShapeLayers : function() {
        this._map.DeleteAllShapeLayers();
    },
    
    DeleteAllShapes : function() {
        this._map.DeleteAllShapes();
    },
    
    DeleteControl : function(_element) {
        this._map.DeleteControl(_element);
    },
    
    DeleteRoute : function() {
        this._map.DeleteRoute();
    },
    
    DeleteShape : function(_shape) {
       this._map.DeleteShape(_shape);
    },
    
    DeleteShapeLayer : function(_layerID) {
        this._map.DeleteShapeLayer(_layerID);
    },
                                                
    EndContinuousPan : function() {
        this._map.EndContinuousPan();
    },
                                                
    Find : function(_what, _where, _findType, _shapeLayerID, _startIndex, _numberOfResults, _showResults, _createResults, _useDefaultDisambiguation, _setBestMapView) {
        var _shapeLayer;
        //Get Layer by ID if supplied
        if (_shapeLayerID) {
            _shapeLayer = this._GetShapeLayerByID(_shapeLayerID);
        }
        this._map.Find(_what, _where, _findType, _shapeLayer, _startIndex, _numberOfResults, _showResults, _createResults, _useDefaultDisambiguation, _setBestMapView, Function.createDelegate(this,this._raiseOnClientFind));
    },
                                                
    GetBirdseyeScene : function() {
        return this._map.GetBirdseyeScene();
    },
                                                
    GetDirections : function(_locations, _distanceUnit, _drawRoute, _routeColor, _routeOptimize, _routeWeight, _routeZIndex, _setBestMapView, _showDisambiguation, _showErrorMessages, _useMWS) {
        //rebuild VE classes
        _VEoptions = new VERouteOptions();
        _VEoptions.DistanceUnit = _distanceUnit;
        _VEoptions.DrawRoute = _drawRoute;
        _VEoptions.RouteColor = this._parseVEColor(_routeColor);
        _VEoptions.RouteOptimize = _routeOptimize;
        _VEoptions.RouteWeight = _routeWeight;
        _VEoptions.RouteZIndex = _routeZIndex;
        _VEoptions.SetBestMapView = _setBestMapView;
        _VEoptions.ShowDisambiguation = _showDisambiguation;
        _VEoptions.ShowErrorMessages = _showErrorMessages;
        _VEoptions.UseMWS = _useMWS;
        _VEoptions.RouteCallback = Function.createDelegate(this,this._raiseOnClientGetDirections);
        if (_locations[0].Latitude) {
            var _points = new Array();
            for (opoint in _locations) {
                _points.push(this._parseVELatLong(_locations[opoint]));
            }
            this._map.GetDirections(_points, _VEoptions);
        }else {
            this._map.GetDirections(_locations, _VEoptions);
        }
    },
                                                
    GetMapView : function() {
        return this._map.GetMapView();
    },
                                                
    GetShapeByID : function(_ID) {
        return this._map.GetShapeByID(_ID);
    },
                                                
    GetShapeLayerByIndex : function(_index) {
        return this._map.GetShapeLayerByIndex(_index);
    },
                                                
    GetShapeLayerCount : function() {
        return this._map.GetShapeLayerCount();
    },
                                                
    GetTileLayerByID : function(_ID) {
        return this._map.GetTileLayerByID(_ID);
    },
                                                
    GetTileLayerByIndex : function(_index) {
        return this._map.GetTileLayerByIndex(_index);
    },
                                                
    GetTileLayerCount : function() {
        return this._map.GetTileLayerCount();
    },
                                                
    HideAllShapeLayers : function() {
        this._map.HideAllShapeLayers();
    },
                                                
    HideControl : function(_element) {
        this._map.HideControl(_element);
    },
                                                
    HideInfoBox : function() {
        this._map.HideInfoBox();
    },                                                        
                                                
    HideTileLayer : function(_layerID) {
        this._map.HideTileLayer(_layerID);
    },                                                        
                                                
    ImportShapeLayerData : function(_layer, _layerSource, _type, _callback, _setBestView) {
        var _velayer = this._parseVEShapeLayer(_layer);
        var _spec = new VEShapeSourceSpecification(_type, _layerSource, _velayer);
        var _fn = null;
        if (_callback && _callback.length > 0) {
            //convert the string into a function to be called
            _fn = eval(_callback);
        }
        this._map.ImportShapeLayerData(_spec, _fn, _setBestView);
    },                                                        
                                                
    IncludePointInView : function(_latlong) {
        this._map.IncludePointInView(this._parseVELatLong(_latlong));
    },                                                        
                                                
    IsBirdseyeAvailable : function() {
        return this._map.IsBirdseyeAvailable();
    },                                                        
                                                
    LatLongToPixel : function(_latlong) {
        return this._map.LatLongToPixel(this._parseVELatLong(_latlong));
    },                                                        
                                                
    Pan : function(_deltaX, _deltaY) {
        this._map.Pan(_deltaX, _deltaY);
    },                                                       
                                                
    PanToLatLong : function(_latlong) {
        this._map.PanToLatLong(this._parseVELatLong(_latlong));
    },                                                        
                                                
    PixelToLatLong : function(_pixel) {
        return this._map.PixelToLatLong(_pixel);
    },                                                        
                                                
    Resize : function(_width, _height) {
        var _w = parseInt(_width);
        var _h = parseInt(_height);
        var _myMap = $get(this._mapContainerID);
        _myMap.style.width = _w + "px";
        _myMap.style.height = _h + "px";
        this._map.Resize(_w, _h);      
    },    
    
    AutoResize: function()
    {
        // Get the container
        var _myMap = $get(this._mapContainerID);
        _w=_myMap.style.width;
        _h=_myMap.style.height;


        // Get the map's span (the container's parent
        var mapSpan = _myMap.parentNode;
        if(mapSpan)
        {
            // Get the parent element
            var parent = mapSpan.parentNode;
            if(parent)
            {
                _w=parent.style.width;
                _h=parent.style.height;
            }    
            
            // Resize the map span (based on parent)
            mapSpan.style.width=_w;
            mapSpan.style.height=_h;
            
            // Resize the map container (based on parent)
            _myMap.style.width = _w;
            _myMap.style.height = _h;
            
            // Resize the map (base on parent)
            this._map.Resize();
        }
    },                                                    
                                                
    SetBirdseyeOrientation : function(_orientation) {
        this._map.SetBirdseyeOrientation(_orientation);
    },                                                        
                                                
    SetBirdseyeScene : function(_latlongOrSceneID, _orientation, _zoomLevel, _callback) {
        //support a single ID parameter.
        if (_latlongOrSceneID.Latitude) {
            var _fn = null;
            if (_callback && _callback.length > 0) {
                //convert the string into a function to be called
                _fn = eval(_callback);
            }
            this._map.SetBirdseyeScene(this._parseVELatLong(_latlongOrSceneID), _orientation, _zoomLevel, _fn);
        }else {
            this._map.SetBirdseyeScene(_latlongOrSceneID);
        }
    },
    
    SetMapView : function(_loc) {
        //support rect or array of latlong
        if (_loc.TopLeftLatLong) {
            this._map.SetMapView(this._parseVELatLongRectangle(_loc));
        }else {
            this._map.SetMapView(this._parseVELatLongArray(_loc));
        }
    },
    
    ShowAllShapeLayers : function() {
        var mapview = this.GetMapView();
        this._map.ShowAllShapeLayers();
        this.SetMapView(mapview);
    },
    
    ShowControl : function(_element) {   
        this._map.ShowControl(_element);
    },                                                 
                                                
    ShowInfoBox : function(_shape, _anchor, _offset) {
        this._map.ShowInfoBox(_shape, _anchor, _offset);
    },                                                        
                                                
    ShowMessage : function(_message) {
        this._map.ShowMessage(_message);
    },                                                        
                                                
    ShowTileLayer : function(_layerID) {
        this._map.ShowTileLayer(_layerID);
    },                                                        
                                                
    StartContinuousPan : function(_x, _y) {
        this._map.StartContinuousPan(_x, _y);
    },                                                                                                                                                       
                                                
    ZoomIn : function() {
        this._map.ZoomIn();
    },
    
    ZoomOut : function() {
        this._map.ZoomOut();
    },
    
    //VE Methods Client Side support only
    GetLeft : function() {
        return this._map.GetLeft();
    },
    
    GetTop : function() {
        return this._map.GetTop();
    },
    
    GetVersion : function() {
        this._map.GetVersion();
    }, 
    
    //Public Property Getters/Setters     
    
    get_VEMap : function() {
        return this._map;
    }, 

    set_VEMap : function(value) {
        this._map = value;
    },
    
    get_BrowsersNotSupported : function() {
        return this._browsersNotSupported;
    }, 

    set_BrowsersNotSupported : function(value) {
        this._browsersNotSupported = value;
    }, 
    
    get_VEAPINotFound : function() {
        return this._vEAPINotFound;
    }, 

    set_VEAPINotFound : function(value) {
        this._vEAPINotFound = value;
    },          
    
    get_MapContainerID : function() {
        return this._mapContainerID;
    }, 

    set_MapContainerID : function(value) {
        this._mapContainerID = value;
    },   
    
    get_AsyncTriggerID : function() {
        return this._asyncTriggerID;
    }, 

    set_AsyncTriggerID : function(value) {
        this._asyncTriggerID = value;
    },     
    
    get_MapDataID : function() {
        return this._mapDataID;
    }, 

    set_MapDataID : function(value) {
        this._mapDataID = value;
    },
    
    get_MapChangesID : function() {
        return this._mapChangesID;
    }, 

    set_MapChangesID : function(value) {
        this._mapChangesID = value;
    },    
    
    get_CommandsID : function() {
        return this._commandsID;
    }, 

    set_CommandsID : function(value) {
        this._commandsID = value;
    }, 
 
    get_CommsFlagID : function() {
        return this._commsFlagID;
    }, 

    set_CommsFlagID : function(value) {
        this._commsFlagID = value;
    },
    
    get_Width : function() {
        return this._width;
    }, 

    set_Width : function(value) {
        if (this._map && value != this._width) {
            this.Resize(value, this._height);
            this._OnPropertyChanged("Width",value);
        }
        this._width = value;
    }, 
    
    get_Height : function() {
        return this._height;
    }, 

    set_Height : function(value) {
        if (this._map && value != this._height) {
            this.Resize(this._width, value);
            this._OnPropertyChanged("Height",value);
        }
        this._height = value;
    },                       

    get_Center : function() {
        return this._center;
    }, 

    set_Center : function(value) {
        if (this._map) {
            if (this._map.GetCenter().Latitude != value.Latitude || this._map.GetCenter().Longitude != value.Longitude) {
                this._map.SetCenter(this._parseVELatLong(value));
            }
            if (value.Latitude != this._center.Latitude || value.Longitude != this._center.Longitude) {
                this._OnPropertyChanged("Center",value);
            }
        }    
        this._center = value;
    },
    
    get_MapMode : function() {
        return this._mapMode;
    }, 

    set_MapMode : function(value) {
        if (this._map) {
            if (this._map.GetMapMode() != value) {
                this._map.SetMapMode(value);
            }
            if (value != this._mapMode) {
                this._OnPropertyChanged("MapMode",value);
            }
        }    
        this._mapMode = value;  
    },
    
    get_MapStyle : function() {
        return this._mapStyle;
    }, 

    set_MapStyle : function(value) {
        if (this._map) {
            if (this._map.GetMapStyle() != value) {
                this._map.SetMapStyle(value);
            }
            if (value != this._mapStyle) {
                this._OnPropertyChanged("MapStyle",value);
            }
        }
        this._mapStyle = value;
    },
    
    get_NavigationControl3D : function() {
        return this._navigationControl3D;
    }, 

    set_NavigationControl3D : function(value) {
        if (this._map && value != this._navigationControl3D) {
            if (value) {
                this._map.Show3DNavigationControl();
            }else {
                this._map.Hide3DNavigationControl();
            }
            this._OnPropertyChanged("NavigationControl3D",value);
        }    
        this._navigationControl3D = value;
    },
    
    get_Dashboard : function() {
        return this._dashboard;
    }, 

    set_Dashboard : function(value) {
        if (this._map && value != this._dashboard) {
            if (value) {
                if(this._dashboardSize != this._map.GetDashboardSize())
                {
                    this._dashboard = value;
                    this._createVEMap();
                }
                else {
                    this._map.ShowDashboard();
                }
            }else {
                this._map.HideDashboard();
            }
            this._OnPropertyChanged("Dashboard",value);
        }
        this._dashboard = value;
    },
    
    get_DashboardSize : function() {
        return this._dashboardSize;
    }, 

    set_DashboardSize : function(value) {
        if (this._map && value != this._dashboardSize) {
            //have to restart the map to do this
            this._dashboardSize = value;
            this._createVEMap();
            this._OnPropertyChanged("DashboardSize",value);
        }
        this._dashboardSize = value;
    },
    
    get_MiniMap : function() {
        return this._miniMap;
    }, 

    set_MiniMap : function(value) {
        if (this._map && value != this._miniMap) {
            if (value) {
                this._map.ShowMiniMap(this._miniMapXoffset, this._miniMapYoffset, this._miniMapSize);
            }else {
                this._map.HideMiniMap();
            }
            this._OnPropertyChanged("MiniMap",value);
        }
        this._miniMap = value;
    },
    
    get_MiniMapXoffset : function() {
        return this._miniMapXoffset;
    }, 

    set_MiniMapXoffset : function(value) {
        if (this._map && value != this._miniMapXoffset) {
            this._map.ShowMiniMap(value, this._miniMapYoffset, this._miniMapSize);
            this._OnPropertyChanged("MiniMapXoffset",value);
        }
        this._miniMapXoffset = value;
    },
    
    get_MiniMapYoffset : function() {
        return this._miniMapYoffset;
    }, 

    set_MiniMapYoffset : function(value) {
        if (this._map && value != this._miniMapYoffset) {
            this._map.ShowMiniMap(this._miniMapXoffset, value, this._miniMapSize);
            this._OnPropertyChanged("MiniMapYoffset",value);
        }
        this._miniMapYoffset = value;
    },
    
    get_MiniMapSize : function() {
        return this._miniMapSize;
    }, 

    set_MiniMapSize : function(value) {
        if (this._map && value != this._miniMapSize) {
            this._map.ShowMiniMap(this._miniMapXoffset, this._miniMapYoffset, value);
            this._OnPropertyChanged("MiniMapSize",value);
        }
        this._miniMapSize = value;
    },
    
    get_TrafficLegend : function() {
        return this._trafficLegend;
    }, 

    set_TrafficLegend : function(value) {
        if (this._map && value != this._trafficLegend) {
            if (value) {
                if (this._trafficLegendX > -1 && this._trafficLegendY > -1) {
                    this._map.ShowTrafficLegend(this._trafficLegendX, this._trafficLegendY);
                }else {
                    this._map.ShowTrafficLegend();
                }
            }else {
                this._map.HideTrafficLegend();
            }
            this._OnPropertyChanged("TrafficLegend",value);
        }
        this._trafficLegend = value;
    },
    
    get_TrafficLegendX : function() {
        return this._trafficLegendX;
    }, 

    set_TrafficLegendX : function(value) {
        if (this._map && value != this._trafficLegendX && this._trafficLegendY > -1) {
            this._map.ShowTrafficLegend(value, this._trafficLegendY);
            this._OnPropertyChanged("TrafficLegendX",value);
        }
        this._trafficLegendX = value;
    },
    
    get_TrafficLegendY : function() {
        return this._trafficLegendY;
    }, 

    set_TrafficLegendY : function(value) {
        if (this._map && value != this._trafficLegendY && this._trafficLegendX > -1) {
            this._map.ShowTrafficLegend(this._trafficLegendX, value);
            this._OnPropertyChanged("TrafficLegendY",value);
        }
        this._trafficLegendY = value;
    },
    
   
    get_Traffic : function() {
        return this._traffic;
    }, 

    set_Traffic : function(value) {
        if (this._map && value != this._traffic) {
            if (value) {
                //validation - client token must be used.
                if (this._clientToken) {
                    this._map.LoadTraffic(value);
                }else {
                    value = false;
                }
            }else {
                this._map.ClearTraffic();
            }        
            this._OnPropertyChanged("Traffic",value);
        }
        this._traffic = value;
    },
    
    get_EnableShapeDisplayThreshold : function() {
        return this._enableShapeDisplayThreshold;
    }, 

    set_EnableShapeDisplayThreshold : function(value) {
        if (this._map && value != this._enableShapeDisplayThreshold) {
            this._map.EnableShapeDisplayThreshold(value);
            this._OnPropertyChanged("EnableShapeDisplayThreshold",value);
        }
        this._enableShapeDisplayThreshold = value;
    },
    
    get_MouseWheelZoomToCenter : function() {
        return this._mouseWheelZoomToCenter;
    }, 

    set_MouseWheelZoomToCenter : function(value) {
        if (this._map && value != this._mouseWheelZoomToCenter) {
            this._map.SetMouseWheelZoomToCenter(value);
            this._OnPropertyChanged("MouseWheelZoomToCenter",value);
        }
        this._mouseWheelZoomToCenter = value;
    },
    
    get_ScaleBarDistanceUnit : function() {
        return this._scaleBarDistanceUnit;
    }, 

    set_ScaleBarDistanceUnit : function(value) {
        if (this._map && value != this._scaleBarDistanceUnit) {
            this._map.SetScaleBarDistanceUnit(value);
            this._OnPropertyChanged("ScaleBarDistanceUnit",value);
        }
        this._scaleBarDistanceUnit = value;
    },
    
    get_ShapesAccuracy : function() {
        return this._shapesAccuracy;
    }, 

    set_ShapesAccuracy : function(value) {
        if (this._map && value != this._shapesAccuracy) {
            this._map.SetShapesAccuracy(value);
            this._OnPropertyChanged("ShapesAccuracy",value);
        }
        this._shapesAccuracy = value;
    },
    
    get_ShapesAccuracyRequestLimit : function() {
        return this._shapesAccuracyRequestLimit;
    }, 

    set_ShapesAccuracyRequestLimit : function(value) {
        if (this._map && value != this._shapesAccuracyRequestLimit) {
            this._map.SetShapesAccuracyRequestLimit(value);
            this._OnPropertyChanged("ShapesAccuracyRequestLimit",value);
        }
        this._shapesAccuracyRequestLimit = value;
    },
    
    get_TileBuffer : function() {
        return this._tileBuffer;
    }, 

    set_TileBuffer : function(value) {
        if (this._map && value != this._tileBuffer) {
            this._map.SetTileBuffer(value);
            this._OnPropertyChanged("TileBuffer",value);
        }
        this._tileBuffer = value;
    },
    
    get_TrafficLegendText : function() {
        return this._trafficLegendText;
    }, 

    set_TrafficLegendText : function(value) {
        if (this._map && value != this._trafficLegendText) {
            this._map.SetTrafficLegendText(value);
            this._OnPropertyChanged("TrafficLegendText",value);
        }
        this._trafficLegendText = value;
    },
    
    get_ZoomLevel : function() {
        return this._zoomLevel;
    }, 

    set_ZoomLevel : function(value) {
        if (this._map) {
            if (this._map.GetZoomLevel() != value) {
                this._map.SetZoomLevel(value);
            }
            if (value != this._zoomLevel) {
                this._OnPropertyChanged("ZoomLevel",value);
            }
        }
        this._zoomLevel = value;
    }, 
    
    get_DisambiguationDialog : function() {
        return this._disambiguationDialog;
    }, 

    set_DisambiguationDialog : function(value) {
        if (this._map && value != this._disambiguationDialog) {
            this._map.ShowDisambiguationDialog(value);
            this._OnPropertyChanged("DisambiguationDialog",value);
        }
        this._disambiguationDialog = value;
    },
    
    get_ClearInfoBoxStyles : function() {
        return this._clearInfoBoxStyles;
    },

    set_ClearInfoBoxStyles : function(value) {
        if (this._map && value != this._clearInfoBoxStyles) {
            if (value) {
                this._map.ClearInfoBoxStyles();
            }else {
                this._map.SetDefaultInfoBoxStyles();
            }
            this._OnPropertyChanged("ClearInfoBoxStyles",value);            
        }
        this._clearInfoBoxStyles = value;
    },
    
    get_FixedMap : function() {
        return this._fixedMap;
    },

    set_FixedMap : function(value) {
        if (this._map && value != this._fixedMap) {
            //have to restart the map to do this
            this._fixedMap = value;
            this._createVEMap();
            this._OnPropertyChanged("FixedMap",value);
        }
        this._fixedMap = value;
    },
    
    get_ShowMapModeSwitch : function() {
        return this._showMapModeSwitch;
    },

    set_ShowMapModeSwitch : function(value) {
        if (this._map && value != this._showMapModeSwitch) {
            //have to restart the map to do this
            this._showMapModeSwitch = value;
            this._createVEMap();
            this._OnPropertyChanged("ShowMapModeSwitch",value);
        }
        this._showMapModeSwitch = value;
    },
        
    get_ShowFindControl : function() {
        return this._showFindControl;
    },

    set_ShowFindControl : function(value) {
        if (this._map && value != this._showFindControl) {
            if (value) {
                this._map.ShowFindControl();
            }else {
                this._map.HideFindControl();
            }
            this._OnPropertyChanged("ShowFindControl",value);            
        }
        this._showFindControl = value;
    },
              
    get_Altitude : function() {
        return this._altitude;
    }, 

    set_Altitude : function(value) {
        if (this._map) {
            if (this._map.GetAltitude() != value) {
                this._map.SetAltitude(value);
            }
            if (value != this._altitude) {
                this._OnPropertyChanged("Altitude",value);
            }
        }
        this._altitude = value;
    },  
    
    get_Heading : function() {
        return this._heading;
    }, 

    set_Heading : function(value) {
        if (this._map) {
            if (this._map.GetHeading() != value) {
                this._map.SetHeading(value);
            }
            if (value != this._heading) {
                this._OnPropertyChanged("Heading",value);
            }
        }
        this._heading = value;
    }, 
    
    get_Pitch : function() {
        return this._pitch;
    }, 

    set_Pitch : function(value) {
        if (this._map) {
            if (this._map.GetPitch() != value) {
                this._map.SetPitch(value);
            }
            if (value != this._pitch) {
                this._OnPropertyChanged("Pitch",value);
            }
        }
        this._pitch = value;
    },           
    
    get_FailedShapeRequest : function() {
        return this._failedShapeRequest;
    },

    set_FailedShapeRequest : function(value) {
        if (this._map && value != this._failedShapeRequest) {
            this._map.SetFailedShapeRequest(value);
            this._OnPropertyChanged("FailedShapeRequest",value);
        }
        this._failedShapeRequest = value;
    },
    
    get_ClientToken : function() {
        return this._clientToken;
    },

    set_ClientToken : function(value) {
        if (this._map && value != this._clientToken) {
            //have to restart the map to do this
            this._clientToken = value;
            this._createVEMap();
        }
        this._clientToken = value;
    },
    
    get_SendLayersToServer : function() {
        return this._SendLayersToServer;
    },

    set_SendLayersToServer : function(value) {
        if (this._map && value != this._SendLayersToServer) {
            this._OnPropertyChanged("SendLayersToServer",value);
        }
        this._SendLayersToServer = value;
    },      
    
    //Server Side Events that are enabled
    get_OnServerLoadMap : function() {
        return this._onServerLoadMap;
    },

    set_OnServerLoadMap : function(value) {
        this._onServerLoadMap = value;
    },

    get_OnServerChangeMapStyle : function() {
        return this._onServerChangeMapStyle;
    },

    set_OnServerChangeMapStyle : function(value) {
        this._onServerChangeMapStyle = value;
    },

    get_OnServerChangeView : function() {
        return this._onServerChangeView;
    },

    set_OnServerChangeView : function(value) {
        this._onServerChangeView = value;
    },

    get_OnServerEndPan : function() {
        return this._onServerEndPan;
    },

    set_OnServerEndPan : function(value) {
        this._onServerEndPan = value;
    },

    get_OnServerEndZoom : function() {
        return this._onServerEndZoom;
    },

    set_OnServerEndZoom : function(value) {
        this._onServerEndZoom = value;
    },

    get_OnServerError : function() {
        return this._onServerError;
    },

    set_OnServerError : function(value) {
        this._onServerError = value;
    },

// Issue:27368 - Removed since this event is to be disabled/removed from the api
//    get_OnServerInitMode : function() {
//        return this._onServerInitMode;
//    },

//    set_OnServerInitMode : function(value) {
//        this._onServerInitMode = value;
//    },

    get_OnServerModeNotAvailable : function() {
        return this._onServerModeNotAvailable;
    },

    set_OnServerModeNotAvailable : function(value) {
        this._onServerModeNotAvailable = value;
    },

    get_OnServerObliqueChange : function() {
        return this._onServerObliqueChange;
    },

    set_OnServerObliqueChange : function(value) {
        this._onServerObliqueChange = value;
    },

    get_OnServerObliqueEnter : function() {
        return this._onServerObliqueEnter;
    },

    set_OnServerObliqueEnter : function(value) {
        this._onServerObliqueEnter = value;
    },

    get_OnServerObliqueLeave : function() {
        return this._onServerObliqueLeave;
    },

    set_OnServerObliqueLeave : function(value) {
        this._onServerObliqueLeave = value;
    },

    get_OnServerResize : function() {
        return this._onServerResize;
    },

    set_OnServerResize : function(value) {
        this._onServerResize = value;
    },

    get_OnServerClick : function() {
        return this._onServerClick;
    },

    set_OnServerClick : function(value) {
        this._onServerClick = value;
    },

    get_OnServerDoubleClick : function() {
        return this._onServerDoubleClick;
    },

    set_OnServerDoubleClick : function(value) {
        this._onServerDoubleClick = value;
    },
    
    get_OnServerFind: function() {
        return this._onServerFind;
    },

    set_OnServerFind : function(value) {
        this._onServerFind = value;
    },
    
    get_OnServerGetDirections: function() {
        return this._onServerGetDirections;
    },

    set_OnServerGetDirections : function(value) {
        this._onServerGetDirections = value;
    },
    
    get_OnServerTokenError : function() {
        return this._onServerTokenError;
    },

    set_OnServerTokenError : function(value) {
        this._onServerTokenError = value;
    },
    
    get_OnServerTokenExpire : function() {
        return this._onServerTokenExpire;
    },

    set_OnServerTokenExpire : function(value) {
        this._onServerTokenExpire = value;
    },                

    //Events
    
    add_OnClientLoadMap : function(handler)       
    {   
        this.get_events().addHandler("OnClientLoadMap", handler);     
    },
    remove_OnClientLoadMap : function(handler)    
    {   
        this.get_events().addHandler("OnClientLoadMap", handler);     
    },
    _raiseOnClientLoadMap : function(_mapEvent)
    {
        this._handlerEvent("OnClientLoadMap", _mapEvent, this._onServerLoadMap);
    },

    add_OnClientChangeMapStyle : function(handler)       
    {   
        this.get_events().addHandler("OnClientChangeMapStyle", handler);     
    },
    remove_OnClientChangeMapStyle : function(handler)    
    {   
        this.get_events().addHandler("OnClientChangeMapStyle", handler);     
    },
    _raiseOnClientChangeMapStyle : function(_mapEvent)
    {
        this._handlerEvent("OnClientChangeMapStyle", _mapEvent, this._onServerChangeMapStyle);
    },

    add_OnClientChangeView : function(handler)       
    {   
        this.get_events().addHandler("OnClientChangeView", handler);     
    },
    remove_OnClientChangeView : function(handler)    
    {   
        this.get_events().addHandler("OnClientChangeView", handler);     
    },
    _raiseOnClientChangeView : function(_mapEvent)
    {
        this._handlerEvent("OnClientChangeView", _mapEvent, this._onServerChangeView);
    },

    add_OnClientEndPan : function(handler)       
    {   
        this.get_events().addHandler("OnClientEndPan", handler);     
    },
    remove_OnClientEndPan : function(handler)    
    {   
        this.get_events().addHandler("OnClientEndPan", handler);     
    },
    _raiseOnClientEndPan : function(_mapEvent)
    {
        this._handlerEvent("OnClientEndPan", _mapEvent, this._onServerEndPan);
    },

    add_OnClientEndZoom : function(handler)       
    {   
        this.get_events().addHandler("OnClientEndZoom", handler);     
    },
    remove_OnClientEndZoom : function(handler)    
    {   
        this.get_events().addHandler("OnClientEndZoom", handler);     
    },
    _raiseOnClientEndZoom : function(_mapEvent)
    {
        this._handlerEvent("OnClientEndZoom", _mapEvent, this._onServerEndZoom);
    },

    add_OnClientError : function(handler)       
    {   
        this.get_events().addHandler("OnClientError", handler);     
    },
    remove_OnClientError : function(handler)    
    {   
        this.get_events().addHandler("OnClientError", handler);     
    },
    _raiseOnClientError : function(_mapEvent)
    {
        this._handlerEvent("OnClientError", _mapEvent, this._onServerError);
    },

// Issue:27368 - Removed since this event is to be disabled/removed from the api
//    add_OnClientInitMode : function(handler)       
//    {   
//        this.get_events().addHandler("OnClientInitMode", handler);     
//    },
//    remove_OnClientInitMode : function(handler)    
//    {   
//        this.get_events().addHandler("OnClientInitMode", handler);     
//    },
//    _raiseOnClientInitMode : function(_mapEvent)
//    {
//        this._handlerEvent("OnClientInitMode", _mapEvent, this._onServerInitMode);
//    },

    add_OnClientModeNotAvailable : function(handler)       
    {   
        this.get_events().addHandler("OnClientModeNotAvailable", handler);     
    },
    remove_OnClientModeNotAvailable : function(handler)    
    {   
        this.get_events().addHandler("OnClientModeNotAvailable", handler);     
    },
    _raiseOnClientModeNotAvailable : function(_mapEvent)
    {
        this._handlerEvent("OnClientModeNotAvailable", _mapEvent, this._onServerModeNotAvailable);
    },

    add_OnClientObliqueChange : function(handler)       
    {   
        this.get_events().addHandler("OnClientObliqueChange", handler);     
    },
    remove_OnClientObliqueChange : function(handler)    
    {   
        this.get_events().addHandler("OnClientObliqueChange", handler);     
    },
    _raiseOnClientObliqueChange : function(_mapEvent)
    {
        this._handlerEvent("OnClientObliqueChange", _mapEvent, this._onServerObliqueChange);
    },

    add_OnClientObliqueEnter : function(handler)       
    {   
        this.get_events().addHandler("OnClientObliqueEnter", handler);     
    },
    remove_OnClientObliqueEnter : function(handler)    
    {   
        this.get_events().addHandler("OnClientObliqueEnter", handler);     
    },
    _raiseOnClientObliqueEnter : function(_mapEvent)
    {
        this._handlerEvent("OnClientObliqueEnter", _mapEvent, this._onServerObliqueEnter);
    },

    add_OnClientObliqueLeave : function(handler)       
    {   
        this.get_events().addHandler("OnClientObliqueLeave", handler);     
    },
    remove_OnClientObliqueLeave : function(handler)    
    {   
        this.get_events().addHandler("OnClientObliqueLeave", handler);     
    },
    _raiseOnClientObliqueLeave : function(_mapEvent)
    {
        this._handlerEvent("OnClientObliqueLeave", _mapEvent, this._onServerObliqueLeave);
    },

    add_OnClientResize : function(handler)       
    {   
        this.get_events().addHandler("OnClientResize", handler);     
    },
    remove_OnClientResize : function(handler)    
    {   
        this.get_events().addHandler("OnClientResize", handler);     
    },
    _raiseOnClientResize : function(_mapEvent)
    {
        this._handlerEvent("OnClientResize", _mapEvent, this._onServerResize);
    },

    add_OnClientStartPan : function(handler)       
    {   
        this.get_events().addHandler("OnClientStartPan", handler);     
    },
    remove_OnClientStartPan : function(handler)    
    {   
        this.get_events().addHandler("OnClientStartPan", handler);     
    },
    _raiseOnClientStartPan : function(_mapEvent)
    {
        this._handlerEvent("OnClientStartPan", _mapEvent, false);
    },

    add_OnClientStartZoom : function(handler)       
    {   
        this.get_events().addHandler("OnClientStartZoom", handler);     
    },
    remove_OnClientStartZoom : function(handler)    
    {   
        this.get_events().addHandler("OnClientStartZoom", handler);     
    },
    _raiseOnClientStartZoom : function(_mapEvent)
    {
        this._handlerEvent("OnClientStartZoom", _mapEvent, false);
    },

    add_OnClientKeyPress : function(handler)       
    {   
        this.get_events().addHandler("OnClientKeyPress", handler);     
    },
    remove_OnClientKeyPress : function(handler)    
    {   
        this.get_events().addHandler("OnClientKeyPress", handler);     
    },
    _raiseOnClientKeyPress : function(_mapEvent)
    {
        this._handlerEvent("OnClientKeyPress", _mapEvent, false);
    },

    add_OnClientKeyDown : function(handler)       
    {   
        this.get_events().addHandler("OnClientKeyDown", handler);     
    },
    remove_OnClientKeyDown : function(handler)    
    {   
        this.get_events().addHandler("OnClientKeyDown", handler);     
    },
    _raiseOnClientKeyDown : function(_mapEvent)
    {
        this._handlerEvent("OnClientKeyDown", _mapEvent, false);
    },

    add_OnClientKeyUp : function(handler)       
    {   
        this.get_events().addHandler("OnClientKeyUp", handler);     
    },
    remove_OnClientKeyUp : function(handler)    
    {   
        this.get_events().addHandler("OnClientKeyUp", handler);     
    },
    _raiseOnClientKeyUp : function(_mapEvent)
    {
        this._handlerEvent("OnClientKeyUp", _mapEvent, false);
    },

    add_OnClientClick : function(handler)       
    {   
        this.get_events().addHandler("OnClientClick", handler);     
    },
    remove_OnClientClick : function(handler)    
    {   
        this.get_events().addHandler("OnClientClick", handler);     
    },
    _raiseOnClientClick : function(_mapEvent)
    {
        if (this._onServerClick) {
            _mapEvent = this._fixMapEventForMode(_mapEvent);
        }
        this._handlerEvent("OnClientClick", _mapEvent, this._onServerClick);
    },
    
    add_OnClientDoubleClick : function(handler)       
    {   
        this.get_events().addHandler("OnClientDoubleClick", handler);     
    },
    remove_OnClientDoubleClick : function(handler)    
    {   
        this.get_events().addHandler("OnClientDoubleClick", handler);     
    },
    _raiseOnClientDoubleClick : function(_mapEvent)
    {
        if (this._onServerDoubleClick) {
            _mapEvent = this._fixMapEventForMode(_mapEvent);
        }   
        this._handlerEvent("OnClientDoubleClick", _mapEvent, this._onServerDoubleClick);
    },

    add_OnClientMouseDown : function(handler)       
    {   
        this.get_events().addHandler("OnClientMouseDown", handler);     
    },
    remove_OnClientMouseDown : function(handler)    
    {   
        this.get_events().addHandler("OnClientMouseDown", handler);     
    },
    _raiseOnClientMouseDown : function(_mapEvent)
    {
        this._handlerEvent("OnClientMouseDown", _mapEvent, false);
    },

    add_OnClientMouseMove : function(handler)       
    {   
        this.get_events().addHandler("OnClientMouseMove", handler);     
    },
    remove_OnClientMouseMove : function(handler)    
    {   
        this.get_events().addHandler("OnClientMouseMove", handler);     
    },
    _raiseOnClientMouseMove : function(_mapEvent)
    {
        this._handlerEvent("OnClientMouseMove", _mapEvent, false);
    }, 

    add_OnClientMouseOut : function(handler)       
    {   
        this.get_events().addHandler("OnClientMouseOut", handler);     
    },
    remove_OnClientMouseOut : function(handler)    
    {   
        this.get_events().addHandler("OnClientMouseOut", handler);     
    },
    _raiseOnClientMouseOut : function(_mapEvent)
    {
        this._handlerEvent("OnClientMouseOut", _mapEvent, false);
    },
    
    add_OnClientMouseOver : function(handler)       
    {   
        this.get_events().addHandler("OnClientMouseOver", handler);     
    },
    remove_OnClientMouseOver : function(handler)    
    {   
        this.get_events().addHandler("OnClientMouseOver", handler);     
    },
    _raiseOnClientMouseOver : function(_mapEvent)
    {
        this._handlerEvent("OnClientMouseOver", _mapEvent, false);
    },
    
    add_OnClientMouseUp : function(handler)       
    {   
        this.get_events().addHandler("OnClientMouseUp", handler);     
    },
    remove_OnClientMouseUp : function(handler)    
    {   
        this.get_events().addHandler("OnClientMouseUp", handler);     
    },
    _raiseOnClientMouseUp : function(_mapEvent)
    {
        this._handlerEvent("OnClientMouseUp", _mapEvent, false);
    },
    
    add_OnClientMouseWheel : function(handler)       
    {   
        this.get_events().addHandler("OnClientMouseWheel", handler);     
    },
    remove_OnClientMouseWheel : function(handler)    
    {   
        this.get_events().addHandler("OnClientMouseWheel", handler);     
    },
    _raiseOnClientMouseWheel : function(_mapEvent)
    {
        this._handlerEvent("OnClientMouseWheel", _mapEvent, false);
    },   
    
    add_OnClientFind : function(handler)       
    {   
        this.get_events().addHandler("OnClientFind", handler);     
    },
    remove_OnClientFind : function(handler)    
    {   
        this.get_events().addHandler("OnClientFind", handler);     
    },
    _raiseOnClientFind : function(_layer, _resultsArray, _placesArray, _hasMore, _veErrorMessage)
    {
        //can't serialize VE object, Need Shape ID only, only the correct fields - parse.
        var _results = new Array();
        for (var _obinding in _resultsArray) {
            _results.push({            
                "Description": _resultsArray[_obinding].Description,
                "IsSponsored": _resultsArray[_obinding].IsSponsored,
                "LatLong": this._cleanVELatLong(_resultsArray[_obinding].LatLong),
                "Name": _resultsArray[_obinding].Name,
                "Phone": _resultsArray[_obinding].Phone,
                "ShapeID": _resultsArray[_obinding].Shape.GetID()
            });
        }
        //can't support FindType - not documented eg YellowPages.
        //"FindType": _resultsArray[obinding].FindType,
        
        var _places = new Array();
        for (var _obinding in _placesArray) {
            var _locations = new Array();
            for (var _obindinglocation in _placesArray[_obinding].Locations) {
                _places.push({            
                    "LatLong": this._cleanVELatLong(_placesArray[_obinding].Locations[_obindinglocation].LatLong),
                    "Precision": _placesArray[_obinding].Locations[_obindinglocation].Precision
                });            
            }
            
            _places.push({            
                "LatLong": this._cleanVELatLong(_placesArray[_obinding].LatLong),
                "Locations": _locations,
                "Name": _placesArray[_obinding].Name,
                "MatchCode": (_placesArray[_obinding].MatchCode) ? _placesArray[_obinding].MatchCode : 0,
                "MatchConfidence": _placesArray[_obinding].MatchConfidence,
                "Precision": _placesArray[_obinding].Precision
            });
        }   
        
        if(!_hasMore) _hasMore = false;     
        if(!_veErrorMessage) _veErrorMessage = "";     
        
        var _mapEvent = {"ResultsArray":_results, "Places": _places, "HasMore": _hasMore, "VEErrorMessage": _veErrorMessage}
        this._handlerEvent("OnClientFind", _mapEvent, this._onServerFind);
    }, 
    
    add_OnClientGetDirections : function(handler)       
    {   
        this.get_events().addHandler("OnClientGetDirections", handler);     
    },
    remove_OnClientGetDirections : function(handler)    
    {   
        this.get_events().addHandler("OnClientGetDirections", handler);     
    },
    _raiseOnClientGetDirections : function(_veroute)
    {
        if (_veroute) {
            //can't serialize VE object, Need Shape ID only, only the correct fields - parse.
            var _routeLegs = new Array();
            for (var _obinding in _veroute.RouteLegs) {
                var _itineraryItems = new Array();
                for (var _obindingitineraryItem in _veroute.RouteLegs[_obinding].Itinerary.Items) {
                    var _itineraryItem = _veroute.RouteLegs[_obinding].Itinerary.Items[_obindingitineraryItem];
                    var _shapeID = "";
                    if (_itineraryItem.Shape) {
                        _shapeID = _itineraryItem.Shape.GetID();
                    }
                    _itineraryItems.push({            
                        "Distance": _itineraryItem.Distance,
                        "LatLong": this._cleanVELatLong(_itineraryItem.LatLong),
                        "ShapeID": _shapeID,
                        "Text": _itineraryItem.Text,
                        "Time": _itineraryItem.Time
                    });           
                }
                
                _routeLegs.push({            
                    "Distance":_veroute.RouteLegs[_obinding].Distance,
                    "Itinerary":{"Items":_itineraryItems},
                    "Time":_veroute.RouteLegs[_obinding].Time
                });
            }
            
                    
            if (!_veroute.Distance) _veroute.Distance = 0.0;
            if (!_veroute.Time) _veroute.Time = 0;
            _route = {
                "Distance":_veroute.Distance,
                "RouteLegs":_routeLegs,
                "Time":_veroute.Time
            };
            this._handlerEvent("OnClientGetDirections", _route, this._onServerGetDirections);
        }
    },
    
    add_OnClientTokenError : function(handler)       
    {   
        this.get_events().addHandler("OnClientTokenError", handler);     
    },
    remove_OnClientTokenError : function(handler)    
    {   
        this.get_events().addHandler("OnClientTokenError", handler);     
    },
    _raiseOnClientTokenError : function(_mapEvent)
    {
        this._handlerEvent("OnClientTokenError", _mapEvent, this._onServerTokenError);
    },
    
    add_OnClientTokenExpire : function(handler)       
    {   
        this.get_events().addHandler("OnClientTokenExpire", handler);     
    },
    remove_OnClientTokenExpire : function(handler)    
    {   
        this.get_events().addHandler("OnClientTokenExpire", handler);     
    },
    _raiseOnClientTokenExpire : function(_mapEvent)
    {
        this._handlerEvent("OnClientTokenExpire", _mapEvent, this._onServerTokenExpire);
    },                          
    
    _handlerEvent: function(_name, _mapEvent, _executeServerSide) {
        var handler = this.get_events().getHandler(_name);
        var EventArgs = new Microsoft.Live.ClientControls.VE.EventArgs(_mapEvent);
        
        if (handler) 
        {
            handler(this.get_element(), EventArgs);
        }
        
        if (_executeServerSide && !EventArgs.get_cancel()) 
        {
           this._sendAsyncEventMessage(_name, Sys.Serialization.JavaScriptSerializer.serialize(_mapEvent));
        }    
    },
    
    _fixMapEventForMode: function(_mapEvent)
    {
        //if 2D mode and server enabled populate Lat/Long values
        if (this._map.GetMapMode() == VEMapMode.Mode2D) {
            _mapEvent.latLong = this._cleanVELatLong(this._map.PixelToLatLong(new VEPixel(_mapEvent.mapX, _mapEvent.mapY)));
        } else {
            _mapEvent.latLong = this._cleanVELatLong(_mapEvent.latLong);
        }  
        return _mapEvent;
    },    
            
    dispose : function() {
        /// <summary>
        ///   Dispose all events and objects.
        /// </summary>     
        this._disposeVEMap();
        Microsoft.Live.ClientControls.VE.Map.callBaseMethod(this, 'dispose') ;
    }          
    
} 

Microsoft.Live.ClientControls.VE.Map.registerClass("Microsoft.Live.ClientControls.VE.Map", Sys.UI.Control);

if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();